package com.sample.snl.frontend;

import com.sample.snl.frontend.LexicalAnalysis.LexicalAnalyser;
import com.sample.snl.frontend.LexicalAnalysis.LexicalResult;
import com.sample.snl.frontend.LexicalAnalysis.Token;
import com.sample.snl.frontend.SyntaxAnalysis.LL1Parser;
import com.sample.snl.frontend.SyntaxAnalysis.SyntaxTree;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.Vector;

public class Main {
    public static void main(String[] args) {
        File file;
        if (args.length > 1) {
            System.out.println("You can specify only one source file at a time!");
            return;
        }
        if (args.length <= 0) {
            System.out.println("Please specify a source code file!");
            return;
        }
        file = new File(args[0]);
        if (!args[0].endsWith(".snl")) {
            System.out.println("Only .snl file allowed!");
            return;
        }

        InputStream in;
        try {
            in = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return;
        }

        LexicalAnalyser lexer = new LexicalAnalyser();
        LexicalResult lexicalResult;
        try {
            lexicalResult = lexer.getResult(new InputStreamReader(in));
            if (lexicalResult.getErrors().size() != 0) {
                System.out.println("Lexical errors were found!");
                lexicalResult.getErrors().forEach(System.err::println);
                return;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        // Write to file
        try {
            int idx = file.getName().indexOf(".");
            String fileName = file.getName().substring(0, idx);
            File path = new File("./lexicalOutput_" + fileName + ".txt");
            if (path.exists()) path.delete();
            path.createNewFile();
            FileWriter fileWriter = new FileWriter(path.getAbsolutePath());
            PrintWriter printWriter = new PrintWriter(fileWriter);
            printWriter.println("Token list:");
            printWriter.println("[Ln : Col] | [    Lexeme] | [Attribute]");
            for (Token token : lexicalResult.getTokenList()) {
                printWriter.printf("[%-3d:%4d] | [%10s] | [%9s]\n", token.line, token.column, token.lexeme, token.type.getStr());
            }
            printWriter.println("Lexical analysis done!");
            System.out.println("Lexical analysis done! Open lexicalOutput_" + fileName + ".txt to see more!");
            printWriter.close();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        Vector<Vector<String>> data = new Vector<Vector<String>>();
        Vector<String> dataTitle = new Vector<String>();
        dataTitle.add("Ln : Col");
        dataTitle.add("Lexeme");
        dataTitle.add("Attribute");
        for (Token token : lexicalResult.getTokenList()) {
            Vector<String> W = new Vector<>();
            W.add(token.line + ":" + token.column);
            W.add(token.lexeme);
            W.add(token.type.getStr());
            data.add(W);
        }

        JFrame jf = new JFrame();
        jf.setBounds(20, 60, 500, 800);
        jf.setTitle("Lexical analysis");
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JTable table = new JTable(data, dataTitle);
        JScrollPane jscrollpane = new JScrollPane(table);
        jf.add(jscrollpane, BorderLayout.CENTER);
        jf.setVisible(true);

        LL1Parser parser = new LL1Parser(lexicalResult.getTokenList());
        parser.parse();
        if (parser.errorList.size() != 0) {
            System.out.println("Syntax errors were found!");
            parser.errorList.forEach(System.err::println);
        } else {
            System.out.println("Syntax analysis finished successfully!");
            SyntaxTree.display(parser.getParsingTree().getRoot());
        }
    }
}
